package com.authine.cloudpivot.controller;

import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.engine.api.model.BaseModel;
import com.authine.cloudpivot.engine.api.model.organization.DepartmentModel;
import com.authine.cloudpivot.engine.api.model.organization.DepartmentUserModel;
import com.authine.cloudpivot.engine.api.model.organization.UserModel;
import com.authine.cloudpivot.engine.api.model.system.AdminModel;
import com.authine.cloudpivot.engine.api.model.system.RelatedCorpSettingModel;
import com.authine.cloudpivot.engine.enums.type.AdminType;
import com.authine.cloudpivot.engine.enums.type.DeptType;
import com.authine.cloudpivot.engine.enums.type.OrgType;
import com.authine.cloudpivot.web.api.controller.base.PermissionController;
import com.authine.cloudpivot.web.api.controller.orgnization.DepartmentController;
import com.authine.cloudpivot.web.api.controller.orgnization.SelectionHelper;
import com.authine.cloudpivot.web.api.handler.CustomizedOrigin;
import com.authine.cloudpivot.web.api.view.ResponseResult;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Api(
        tags = {"组织机构::部门"}
)
@RestController
@RequestMapping({"/api/organization/department"})
@Validated
@CustomizedOrigin(
        level = 1
)
public class ExDepartmentController extends PermissionController {

    private static final Logger log = LoggerFactory.getLogger(DepartmentController.class);
    @Autowired
    private SelectionHelper selectionHelper;

    @GetMapping({"/tree"})
    public ResponseResult<Map<String, List<DepartmentModel>>> tree(@RequestParam(defaultValue = "") String deptIds, @RequestParam(required = false) String filterType, @RequestParam(required = false) String corpId, @RequestParam(required = false) String sourceType, @RequestParam(required = false) String excludeCorpId, String selectUserIds, @RequestParam(required = false) String formRootDeptIds) {
        StopWatch watch = new StopWatch();
        watch.start();
        List<String> deptIdParams = null;
        deptIds = this.filterRelateDeptId(deptIds);
        if (StringUtils.isNotEmpty(deptIds)) {
            deptIdParams = Splitter.on(",").splitToList(deptIds);
        }

        String userId = this.getUserId();
        log.info("用户id：userId={}", JSON.toJSONString(userId));
        Map<String, List<DepartmentModel>>  display;
        if ("self".equals(filterType)) {
            display = this.selectionHelper.selectionTreeHandler2(deptIds, filterType, sourceType, corpId, this.getUserId());
            watch.stop();
            log.info("process time:{}", watch.getLastTaskTimeMillis());
            return this.getOkResponseResult(display, "查询树形组织机构成功");
        } else if ("root_display".equals(filterType) && StringUtils.isNotEmpty(deptIds)) {
            display = this.selectionTreeHandler2RootDisplay(deptIds);
            UserModel user = this.getOrganizationFacade().getUser(userId);
            Map<String, List<DepartmentModel>> myDepartment = this.getMyDepartment(user.getCorpId(), user);
            List<DepartmentModel> models = (List)display.get("departmentList");
            Map<String, List<DepartmentModel>> finalData = this.selectionHelper.getMyDepartment(models, user, sourceType, myDepartment);
            finalData.putAll(display);
            watch.stop();
            log.info("process time:{}", watch.getLastTaskTimeMillis());
            return this.getOkResponseResult(finalData, "查询树形组织机构成功");
        } else {
            watch.stop();
            log.info("process time1:{}", watch.getLastTaskTimeMillis());
            watch.start();
            List<DepartmentModel> departmentList = new ArrayList();
            Map<String, List<DepartmentModel>> result = Maps.newHashMap();
            String mainOrgType = null;
            String excludedeptid = null;
            if (StringUtils.isNotEmpty(corpId) && "MAIN_ORG".equals(corpId)) {
                corpId = null;
                mainOrgType = OrgType.MAIN.getName();
            } else if (StringUtils.isNotEmpty(corpId) && corpId.split("@@").length == 2) {
                if (corpId.split("@@")[1].startsWith("excludedeptid")) {
                    excludedeptid = corpId.split("@@")[1].replace("excludedeptid-", "");
                }

                corpId = corpId.split("@@")[0];
            }
            final String exid = excludedeptid;


            AdminModel appAdminByUser = this.getAppAdminByUserId(userId);
            SelectionHelper.SelectionFilter filterInfo = this.selectionHelper.relatedSelection(filterType, sourceType, corpId, appAdminByUser);
            boolean finalNeedFilterCorp = filterInfo.isNeedFilterCorp();
            boolean needFilter = filterInfo.isNeedFilterAppAdmin();
            String finalCorpId = filterInfo.getCorpId();
            boolean isFirst = StringUtils.isEmpty(deptIds);
            Set<String> loginUserDeptPermAndSelectUsersMixed = null;
            Set<String> allPathDeptSet;
            DepartmentModel corpRootDept;
            if (filterInfo.isNeedFilterAppAdmin() && appAdminByUser != null && appAdminByUser.getAdminType() == AdminType.APP_MNG) {
                allPathDeptSet = this.getManagePermChildDepartmentId(userId);
                if (CollectionUtils.isEmpty((Collection)allPathDeptSet)) {
                    result.put("departmentList", departmentList);
                    return this.getOkResponseResult(result, "查询树形组织机构成功");
                }

                if (StringUtils.isNotEmpty(selectUserIds)) {
                    loginUserDeptPermAndSelectUsersMixed = this.getLoginUserDeptPermAndSelectUsersMixed((Set)allPathDeptSet, selectUserIds);
                    deptIds = StringUtils.join(this.getParentDeptIdsByMixed(loginUserDeptPermAndSelectUsersMixed), ",");
                } else if (isFirst) {

                    Set<String> parentDeptIds = this.getParentDeptIds(appAdminByUser);;
                    if (needFilter && parentDeptIds.size() > 0 && !((List<DepartmentModel> )this.getOrganizationFacade().getDepartmentsByDeptIds(new ArrayList(parentDeptIds))).stream().filter((dept) -> {
                        return StringUtils.isNotEmpty(finalCorpId) ? finalCorpId.equals(dept) : true;
                    }).findAny().isPresent()) {
                        corpRootDept = this.getOrganizationFacade().getRootDepartmentByCorpId(finalCorpId);
                        if (((Set)allPathDeptSet).contains(corpRootDept.getId())) {
                            parentDeptIds.add(corpRootDept.getId());
                        }
                    }

                    deptIds = StringUtils.join(parentDeptIds, ",");
                }
            } else {
                allPathDeptSet = new HashSet(2);
            }

            watch.stop();
            log.info("process time2:{}", watch.getLastTaskTimeMillis());
            watch.start();
            List<DepartmentModel> departIdList =new ArrayList<>();
            if (CollectionUtils.isEmpty(this.getAdminFacade().getAdminByUserId(userId))) {
                departIdList = this.getOrganizationFacade().getDepartmentsByUserId(userId);
                boolean isEDU = departIdList.stream().anyMatch((dept) -> {
                    return DeptType.EDU_DEPT == dept.getDeptType();
                });
                if (isEDU && StringUtils.isEmpty(deptIds)) {
                    deptIds = StringUtils.join((Iterable)departIdList.stream().map(DepartmentModel::getParentId).collect(Collectors.toSet()), ",");
                }
            }

            if (StringUtils.isEmpty(deptIds) && StringUtils.isNotEmpty(selectUserIds)) {
                result.put("departmentList", this.selectionHelper.filterDeptTree((List)departmentList, formRootDeptIds, sourceType));
                return this.getOkResponseResult(result, "查询树形组织机构成功");
            } else {
                List<String> departIds;
                if (CollectionUtils.isNotEmpty(deptIdParams) && StringUtils.isNotEmpty(deptIds)) {
                    departIds = Splitter.on(',').splitToList(deptIds);
                    List<String> tempIdList = Lists.newArrayList();
                    Iterator var26 = departIds.iterator();

                    while(var26.hasNext()) {
                        String id = (String)var26.next();
                        if (deptIdParams.contains(id)) {
                            tempIdList.add(id);
                        }
                    }

                    deptIds = StringUtils.join(tempIdList, ",");
                }

                watch.stop();
                log.info("process time3:{}", watch.getLastTaskTimeMillis());
                watch.start();
                List deptByScope;
                if (StringUtils.isEmpty(deptIds)) {

                    UserModel user = this.getOrganizationFacade().getUser(userId);
                    log.info("用户：user={}", JSON.toJSONString(user));
                    departmentList = (List)this.getRootDepartmentModels("main", sourceType).stream().filter((dept) -> {
                        return finalNeedFilterCorp && StringUtils.isNotEmpty(finalCorpId) ? finalCorpId.equals(dept.getCorpId()) : true;
                    }).collect(Collectors.toList());
                    if (StringUtils.isNotEmpty(excludedeptid)) {
                        departmentList = (List)(departmentList).stream().filter((dept) -> {
                            return !exid.equals(dept.getId());
                        }).collect(Collectors.toList());
                    }

                    if (CollectionUtils.isEmpty((Collection)departmentList)) {
                        corpRootDept = this.getOrganizationFacade().getRootDepartmentByCorpId(finalCorpId);
                        if (Objects.nonNull(corpRootDept)) {
                            if (corpRootDept.isLeaf()) {
                                List<UserModel> userModels = this.getOrganizationFacade().getUsersByDeptId(corpRootDept.getId());
                                corpRootDept.setEmployees(CollectionUtils.isEmpty(userModels) ? 0 : userModels.size());
                            }

                            ((List)departmentList).add(corpRootDept);
                        }
                    }

                    deptByScope = this.selectionHelper.filterDeptTree((List)departmentList, formRootDeptIds, sourceType);
                    ((List)departmentList).clear();
                    ((List)departmentList).addAll(deptByScope);
                    Map<String, List<DepartmentModel>> oldMyDept = this.getMyDepartment(finalCorpId, user);
                    Map<String, List<DepartmentModel>> myDepartment = this.selectionHelper.getMyDepartment(deptByScope, user, sourceType, oldMyDept);
                    result.putAll(myDepartment);
                    watch.stop();
                    log.info("process time4:{}", watch.getLastTaskTimeMillis());
                    watch.start();
                } else {
                    String[] departIdLists = deptIds.split(",");
                    if (departIdLists.length == 1 && !isFirst) {
                        if (needFilter) {
                            departmentList = (List)this.getOrganizationFacade().getDepartmentsByParentId(departIdLists[0], true).stream().filter((dept) -> {
                                return !finalNeedFilterCorp ? true : finalCorpId.equals(dept.getCorpId()) && allPathDeptSet.contains(dept.getId());
                            }).collect(Collectors.toList());
                        } else {
                            departmentList = (List)this.getOrganizationFacade().getDepartmentsByParentId(departIdLists[0], true).stream().filter((dept) -> {
                                return !finalNeedFilterCorp ? true : finalCorpId.equals(dept.getCorpId()) && Boolean.TRUE.equals(dept.getIsShow());
                            }).collect(Collectors.toList());
                        }

                        departmentList = (List)departmentList.stream().filter((item) -> {
                            return Boolean.TRUE.equals(item.getIsShow());
                        }).collect(Collectors.toList());
                        watch.stop();
                        log.info("process time5:{}", watch.getLastTaskTimeMillis());
                        watch.start();
                        if (StringUtils.isNotEmpty(excludeCorpId)) {
                            departmentList = (List)departmentList.stream().filter((dept) -> {
                                return !excludeCorpId.equals(dept.getCorpId());
                            }).collect(Collectors.toList());
                        }

                        if (StringUtils.isNotEmpty(mainOrgType)) {
                            RelatedCorpSettingModel mainRelatedCorpSettingModel = (RelatedCorpSettingModel)this.getSystemManagementFacade().getAllRelatedCorpSettingModelByOrgType(OrgType.MAIN).get(0);
                            departmentList = (List)departmentList.stream().filter((dept) -> {
                                return mainRelatedCorpSettingModel.getCorpId().equals(dept.getCorpId());
                            }).collect(Collectors.toList());
                        }

                        if (StringUtils.isNotEmpty(excludedeptid)) {
                            departmentList = (List)departmentList.stream().filter((dept) -> {
                                return !exid.equals(dept.getId());
                            }).collect(Collectors.toList());
                        }

                        result.put("departmentList", departmentList);
                        watch.stop();
                        log.info("process time6:{}", watch.getLastTaskTimeMillis());
                        log.info("process time total:{}", watch.getTotalTimeMillis());
                        return this.getOkResponseResult(result, "查询树形组织机构成功");
                    }

                    String[] var45 = departIdList.stream().map(dept ->dept.getId()).toArray(String[]::new);
                    int var47 = departIdList.size();

                    for(int var50 = 0; var50 < var47; ++var50) {
                        String depart = var45[var50];
                        if (!needFilter || ((Set)allPathDeptSet).contains(depart)) {
                            DepartmentModel department = this.getOrganizationFacade().getDepartment(depart, true);
                            if (department != null && Boolean.TRUE.equals(department.getIsShow())) {
                                if (department.isLeaf()) {
                                    List<UserModel> userModels = this.getOrganizationFacade().getUsersByDeptId(department.getId());
                                    department.setEmployees(CollectionUtils.isEmpty(userModels) ? 0 : userModels.size());
                                }

                                ((List)departmentList).add(department);
                            }
                        }
                    }

                    deptByScope = this.selectionHelper.filterDeptTree((List)departmentList, formRootDeptIds, sourceType);
                    ((List)departmentList).clear();
                    ((List)departmentList).addAll(deptByScope);
                }

                watch.stop();
                log.info("process time7:{}", watch.getLastTaskTimeMillis());
                watch.start();
                if (CollectionUtils.isNotEmpty((Collection)departmentList)) {
                    departmentList = (List)(departmentList).stream().filter((item) -> {
                        return Boolean.TRUE.equals(item.getIsShow()) && Boolean.TRUE.equals(item.getEnabled());
                    }).collect(Collectors.toList());
                    departmentList = (List)departmentList.stream().filter((item) -> {
                        return !finalNeedFilterCorp || finalCorpId.equals(item.getCorpId());
                    }).collect(Collectors.toList());
                    if (StringUtils.isNotEmpty(excludeCorpId)) {
                        departmentList = (List)(departmentList).stream().filter((dept) -> {
                            return !excludeCorpId.equals(dept.getCorpId());
                        }).collect(Collectors.toList());
                    }

                    if (StringUtils.isNotEmpty(mainOrgType)) {
                        RelatedCorpSettingModel mainRelatedCorpSettingModel = (RelatedCorpSettingModel)this.getSystemManagementFacade().getAllRelatedCorpSettingModelByOrgType(OrgType.MAIN).get(0);
                        departmentList = (List)(departmentList).stream().filter((dept) -> {
                            return mainRelatedCorpSettingModel.getCorpId().equals(dept.getCorpId());
                        }).collect(Collectors.toList());
                    }
                    if (StringUtils.isNotEmpty(excludedeptid)) {
                        departmentList = (List)(departmentList).stream().filter((dept) -> {
                            return !exid.equals(dept.getId());
                        }).collect(Collectors.toList());
                    }
                }

                ((List)departmentList).stream().sorted(Comparator.comparing(BaseModel::getCreatedTime));
                watch.stop();
                log.info("process time8:{}", watch.getLastTaskTimeMillis());
                log.info("process time total:{}", watch.getTotalTimeMillis());
                this.selectionHelper.parseDeptParentName((List)departmentList);
                result.put("departmentList", departmentList);
                return this.getOkResponseResult(result, "查询树形组织机构成功");
            }
        }
    }


    private String filterRelateDeptId(String originalDept) {
        if (!StringUtils.isBlank(originalDept) && originalDept.contains(",")) {
            List<String> deptIdList = Arrays.asList(originalDept.split(","));
            Map<String, List<DepartmentModel>> deptMap = this.getOrganizationFacade().getDepartmentsByParentIds(deptIdList);
            List<String> list = deptIdList.stream().filter((deptId) -> {
                List<String> parentIdList = (List)(deptMap.get(deptId)).stream().map(BaseModel::getId).collect(Collectors.toList());
                Stream var10000 = parentIdList.stream();
                deptIdList.getClass();
                List<String> matchList = (List)var10000.filter(deptIdList::contains).collect(Collectors.toList());
                return matchList.size() == 1;
            }).collect(Collectors.toList());
            return StringUtils.join(list, ",");
        } else {
            return originalDept;
        }
    }

    private Map<String, List<DepartmentModel>> getMyDepartment(String finalCorpId, UserModel user) {
        Map<String, List<DepartmentModel>> result = new HashMap();
        DepartmentModel department = this.getOrganizationFacade().getDepartment(user.getDepartmentId());
        if (department == null) {
            result.put("myDepartment", null);
            return result;
        } else {
            log.info("我的部门数据：department={}", JSON.toJSONString(department));
            if (department.isLeaf()) {
                department.setEmployees(this.getUserFacade().countEnableUsersByDeptId(department.getId()));
            }

            if (!StringUtils.equals(department.getCorpId(), finalCorpId)) {
                result.put("myDepartment", null);
            } else {
                result.put("myDepartment", Collections.singletonList(department));
            }

            return result;
        }
    }


    private Set<String> getLoginUserDeptPermAndSelectUsersMixed(Set<String> allPathDeptSet, String selectUserIds) {
        if (StringUtils.isBlank(selectUserIds)) {
            return null;
        } else {
            String[] split = selectUserIds.split(",");
            List<DepartmentUserModel> departmentUserModels = new ArrayList();
            String[] var5 = split;
            int var6 = split.length;

            for(int var7 = 0; var7 < var6; ++var7) {
                String userId = var5[var7];
                departmentUserModels.addAll(this.getOrganizationFacade().getDepartmentUsersByUserId(userId));
            }

            List<String> collect = (List)departmentUserModels.stream().map(DepartmentUserModel::getDeptId).collect(Collectors.toList());
            Set<String> deptChildIdSet = (Set)this.getOrganizationFacade().getDepartmentsChildList(collect, false).stream().map(BaseModel::getId).collect(Collectors.toSet());
            deptChildIdSet.retainAll(allPathDeptSet);
            return deptChildIdSet;
        }
    }


    private Set<String> getParentDeptIdsByMixed(Set<String> loginUserDeptPermAndSelectUsersMixed) {
        if (CollectionUtils.isEmpty(loginUserDeptPermAndSelectUsersMixed)) {
            return null;
        } else {
            List<DepartmentModel> mixed = this.getOrganizationFacade().getDepartmentsByDeptIds(new ArrayList(loginUserDeptPermAndSelectUsersMixed));
            mixed.removeIf((departmentModel) -> {
                return StringUtils.isNotEmpty(departmentModel.getParentId()) && loginUserDeptPermAndSelectUsersMixed.contains(departmentModel.getParentId());
            });
            return (Set)mixed.stream().map(BaseModel::getId).collect(Collectors.toSet());
        }
    }

    private List<DepartmentModel> getRootDepartmentModels(String corpId, String sourceType) {
        List<DepartmentModel> rootDepartments = null;
        if (StringUtils.isEmpty(corpId)) {
            rootDepartments = this.getOrganizationFacade().getRootDepartment();
        } else if (StringUtils.isNotEmpty(sourceType)) {
            RelatedCorpSettingModel relatedCorpSettingModel = this.getSystemManagementFacade().getRelatedCorpSettingModelByCorpId(corpId);
            switch(relatedCorpSettingModel.getOrgType()) {
                case MAIN:
                    rootDepartments = this.getOrganizationFacade().getRootDepartment();
                    break;
                case RELEVANCE:
                    if (rootDepartments == null) {
                        rootDepartments = Lists.newArrayList();
                    }

                    ((List)rootDepartments).clear();
                    DepartmentModel relatedCorpRootDept = this.getOrganizationFacade().getRootDepartmentByCorpId(corpId);
                    ((List)rootDepartments).add(relatedCorpRootDept);
            }
        } else {
            rootDepartments = this.getOrganizationFacade().getRootDepartment();
        }

        if (CollectionUtils.isNotEmpty((Collection)rootDepartments)) {
            this.initRootDepartmentModels((List)rootDepartments);
        }

        return (List)rootDepartments;
    }

    private void initRootDepartmentModels(List<DepartmentModel> rootDepartments) {
        Map<String, Long> userCountMap = this.getOrganizationFacade().countUserGroupByCorpId();
        Iterator var3 = rootDepartments.iterator();

        while(var3.hasNext()) {
            DepartmentModel rootDepartment = (DepartmentModel)var3.next();
            if (Objects.nonNull(rootDepartment) && rootDepartment.isLeaf()) {
                rootDepartment.setEmployees(Objects.isNull(userCountMap.get(rootDepartment.getCorpId())) ? 0 : ((Long)userCountMap.get(rootDepartment.getCorpId())).intValue());
            }
        }

    }



    public Map<String, List<DepartmentModel>> selectionTreeHandler2RootDisplay(String deptIds) {
        List<DepartmentModel> departmentList = new ArrayList();
        Map<String, List<DepartmentModel>> result = Maps.newHashMap();
        String userId = this.getUserId();
        UserModel user = this.getOrganizationFacade().getUser(userId);
        if (user != null && StringUtils.isNotEmpty(user.getCorpId())) {
            RelatedCorpSettingModel settingModel = this.getSystemManagementFacade().getRelatedCorpSettingModelByCorpId(user.getCorpId());
            if (settingModel != null && settingModel.getOrgType() == OrgType.MAIN) {
                departmentList.addAll(this.getDepartmentByDeptIds(deptIds));
                Set<String> collect = (Set)departmentList.stream().map((departmentModel) -> {
                    return departmentModel.getCorpId();
                }).collect(Collectors.toSet());
                List<DepartmentModel> rootDepartment = this.getOrganizationFacade().getRootDepartment();
                List<DepartmentModel> departmentModels = (List)rootDepartment.stream().filter((departmentModel) -> {
                    return departmentModel.getEnabled() && !collect.contains(departmentModel.getCorpId());
                }).collect(Collectors.toList());
                Iterator var17 = departmentModels.iterator();

                while(var17.hasNext()) {
                    DepartmentModel department = (DepartmentModel)var17.next();
                    if (department != null && Boolean.TRUE.equals(department.getIsShow())) {
                        if (department.isLeaf()) {
                            List<UserModel> userModels = this.getOrganizationFacade().getUsersByDeptId(department.getId());
                            department.setEmployees(CollectionUtils.isEmpty(userModels) ? 0 : userModels.size());
                        }

                        departmentList.add(department);
                    }
                }
            } else {
                String[] departIdList = deptIds.split(",");
                String[] var8 = departIdList;
                int var9 = departIdList.length;

                for(int var10 = 0; var10 < var9; ++var10) {
                    String depart = var8[var10];
                    DepartmentModel department = this.getOrganizationFacade().getDepartment(depart, true);
                    if (department != null && Boolean.TRUE.equals(department.getIsShow())) {
                        if (department.isLeaf()) {
                            List<UserModel> userModels = this.getOrganizationFacade().getUsersByDeptId(department.getId());
                            department.setEmployees(CollectionUtils.isEmpty(userModels) ? 0 : userModels.size());
                        }

                        departmentList.add(department);
                    }
                }
            }
        } else {
            departmentList.addAll(this.getDepartmentByDeptIds(deptIds));
        }

        result.put("departmentList", departmentList);
        return result;
    }


    private List<DepartmentModel> getDepartmentByDeptIds(String deptIds) {
        List<DepartmentModel> departmentList = new ArrayList();
        String[] departIdList = deptIds.split(",");
        String[] var4 = departIdList;
        int var5 = departIdList.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String depart = var4[var6];
            DepartmentModel department = this.getOrganizationFacade().getDepartment(depart, true);
            if (department != null && Boolean.TRUE.equals(department.getIsShow())) {
                if (department.isLeaf()) {
                    department.setEmployees(this.getUserFacade().countEnableUsersByDeptId(department.getId()));
                }

                departmentList.add(department);
            }
        }

        return departmentList;
    }

}
